package com.example.takeaway.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.takeaway.common.ResponseEnum;
import com.example.takeaway.converter.CartItemConverter;
import com.example.takeaway.exception.BusException;
import com.example.takeaway.mapper.CartItemMapper;
import com.example.takeaway.mapper.DishMapper;
import com.example.takeaway.model.bo.CartItem;
import com.example.takeaway.model.bo.Dish;
import com.example.takeaway.model.dto.AddCartItemDTO;
import com.example.takeaway.model.vo.CartItemVO;
import com.example.takeaway.model.vo.CartVO;
import com.example.takeaway.service.CartItemService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 购物车项表 服务实现类
 * </p>
 *
 * @author 邢晨旭
 * @since 2023-10-12
 */
@Service
public class CartItemServiceImpl extends ServiceImpl<CartItemMapper, CartItem> implements CartItemService {

    @Resource
    CartItemConverter cartItemConverter;

    @Resource
    DishMapper dishMapper;

    @Override
    public void addCart(AddCartItemDTO param) {
        //判断菜品是否有效
        boolean flag = true;
        //List<CartItem> cartItems = baseMapper.queryCartItem(param.getShopId(), param.getDishId(), UserInfoContext.get().getUserId());
        List<CartItem> cartItems = baseMapper.queryCartItem(param.getShopId(), param.getDishId(), 111L);
        if (cartItems.size() > 0) {
            //有这个菜品 判断规格是否相同
            for (CartItem cartItem : cartItems) {
                if (compareSpecification(cartItem.getSpecification(), param.getSpecification())) {
                    //规格相同 数量相加
                    //更新商品的价格为最新的价格
                    check(param.getDishId(), cartItem);
                    cartItem.setQuantity(cartItem.getQuantity() + param.getQuantity());
                    baseMapper.updateById(cartItem);
                    flag = false;
                    break;
                }
            }
        }
        if (flag) {
            //没有这个菜品 直接添加
            CartItem cartItem = cartItemConverter.toCartItem(param);
            check(param.getDishId(), cartItem);
            baseMapper.insert(cartItem);
        }
    }

    @Override
    public void changeNum(Long id, Integer num) {
        CartItem cartItem = baseMapper.queryCartItemById(id);
        if (cartItem == null) {
            throw new BusException(ResponseEnum.CART_ITEM_NOT_EXIST);
        }
        check(cartItem.getDishId(), cartItem);
        int newNum = cartItem.getQuantity() + num;
        if (newNum > 0) {
            cartItem.setQuantity(newNum);
            baseMapper.updateById(cartItem);
            return;
        }
        baseMapper.delById(id);
    }

    @Override
    public void delCart(Long shopId, Long userId) {
        baseMapper.deleteByShopId(shopId, userId);
    }

    @Override
    public CartVO queryCartList(Long shopId, Long userId) {
        CartVO cartVO = new CartVO();
        List<CartItem> cartItems = baseMapper.queryCartItem(shopId, null, userId);
        if (cartItems.size() == 0) {
            return cartVO;
        }
        List<Long> dishIds = cartItems.stream().map(CartItem::getDishId).collect(Collectors.toList());
        List<Dish> dishes = dishMapper.selectBatchIds(dishIds);
        Map<Long, Dish> dishMap = dishes.stream().collect(Collectors.toMap(Dish::getId, dish -> dish));
        //todo 区分有效无效的菜品
        int num = 0;
        BigDecimal totalPrice = BigDecimal.ZERO;
        cartVO.setCartItems(cartItemConverter.toCartItemVO(cartItems));
        for (CartItemVO item : cartVO.getCartItems()) {
            Dish dish = dishMap.get(item.getDishId());
            BigDecimal price = item.getPrice().multiply(BigDecimal.valueOf(item.getQuantity()));
            item.setPrice(price);
            item.setDishName(dish.getDishName());
            item.setImage(dish.getImage());
            num += item.getQuantity();
            totalPrice = totalPrice.add(price);
        }
        cartVO.setPackagingPrice(BigDecimal.valueOf(num).multiply(BigDecimal.ONE));
        cartVO.setTotalPrice(totalPrice.add(cartVO.getPackagingPrice()));
        cartVO.setTotalNum(num);
        return cartVO;
    }

    private void check(Long dishId, CartItem cartItem) {
        Dish dish = dishMapper.selectById(dishId);
        if (!(dish != null && dish.getIsDeleted() == 0 && dish.getStatus() == 1)) {
            throw new BusException(ResponseEnum.DISH_NOT_EXIST);
        }
        cartItem.setDishName(dish.getDishName());
        cartItem.setPrice(dish.getPrice());
    }

    private Boolean compareSpecification(String specification1, String specification2) {
        JSONArray jsonArray1 = JSONArray.parseArray(specification1);
        JSONArray jsonArray2 = JSONArray.parseArray(specification2);
        Map<Long, String> map1 = jsonArray1.stream().map(item -> (JSONObject) item).collect(Collectors.toMap(item -> item.getLong("id"), item -> item.getString("value")));
        Map<Long, String> map2 = jsonArray2.stream().map(item -> (JSONObject) item).collect(Collectors.toMap(item -> item.getLong("id"), item -> item.getString("value")));
        if (map1.size() != map2.size()) {
            return false;
        }
        for (Map.Entry<Long, String> entry : map1.entrySet()) {
            Long key = entry.getKey();
            String value = entry.getValue();
            if (!map2.containsKey(key) || !map2.get(key).equals(value)) {
                return false;
            }
        }
        return true;
    }

}
